package service

import (
	"context"
	"encoding/json"
	"fmt"
	"gin-zc/util" // 包含RedisClient实例
	"time"

	"github.com/go-redis/redis/v8"
)

// 全局上下文（建议在Gin请求中使用c.Request.Context()）
var ctx = context.Background()

// SetString 存储字符串（key-value）
// key: 键名
// value: 字符串值
// expiration: 过期时间（0表示永久）
func SetString(key string, value string, expiration time.Duration) error {
	return util.RedisClient.Set(ctx, key, value, expiration).Err()
}

// GetString 获取字符串值
// 返回值：value（键不存在则为空字符串）、error（非redis.Nil的错误）
func GetString(key string) (string, error) {
	val, err := util.RedisClient.Get(ctx, key).Result()
	if err != nil {
		if err == redis.Nil {
			// 键不存在，返回空字符串和nil（业务层可判断）
			return "", nil
		}
		return "", err // 其他错误（如连接失败）
	}
	return val, nil
}

// SetObject 存储结构体/对象（自动序列化为JSON字符串）
func SetObject(key string, data interface{}, expiration time.Duration) error {
	// 序列化为JSON
	dataJSON, err := json.Marshal(data)
	if err != nil {
		return err
	}
	return util.RedisClient.Set(ctx, key, dataJSON, expiration).Err()
}

// GetObject 读取对象（反序列化为指定结构体）
// data: 传入结构体指针（如&User{}），用于接收反序列化结果
func GetObject(key string, data interface{}) error {
	val, err := util.RedisClient.Get(ctx, key).Result()
	if err != nil {
		if err == redis.Nil {
			// 键不存在，返回自定义错误（业务层可识别）
			return fmt.Errorf("key %s not found", key)
		}
		return err
	}
	// 反序列化为结构体
	return json.Unmarshal([]byte(val), data)
}

// DelString 删除字符串键
func DelString(key string) error {
	return util.RedisClient.Del(ctx, key).Err()
}

// HSet 存储哈希字段（单个字段）
// key: 哈希表键名
// field: 字段名
// value: 字段值（字符串）
func HSet(key, field, value string) error {
	return util.RedisClient.HSet(ctx, key, field, value).Err()
}

// HGet 获取哈希字段值
func HGet(key, field string) (string, error) {
	val, err := util.RedisClient.HGet(ctx, key, field).Result()
	if err != nil {
		if err == redis.Nil {
			return "", nil // 字段不存在
		}
		return "", err
	}
	return val, nil
}

// HSetMap 批量存储哈希字段（通过map）
func HSetMap(key string, data map[string]interface{}) error {
	return util.RedisClient.HSet(ctx, key, data).Err()
}

// HGetAll 获取哈希表所有字段和值
func HGetAll(key string) (map[string]string, error) {
	return util.RedisClient.HGetAll(ctx, key).Result()
}

// HDel 删除哈希字段
func HDel(key string, fields ...string) error {
	return util.RedisClient.HDel(ctx, key, fields...).Err()
}

// LPush 从列表左侧（头部）插入元素
func LPush(key string, values ...interface{}) error {
	return util.RedisClient.LPush(ctx, key, values...).Err()
}

// RPush 从列表右侧（尾部）插入元素
func RPush(key string, values ...interface{}) error {
	return util.RedisClient.RPush(ctx, key, values...).Err()
}

// LPop 从列表左侧（头部）弹出元素（移除并返回）
func LPop(key string) (string, error) {
	val, err := util.RedisClient.LPop(ctx, key).Result()
	if err != nil {
		if err == redis.Nil {
			return "", nil // 列表为空
		}
		return "", err
	}
	return val, nil
}

// RPop 从列表右侧（尾部）弹出元素
func RPop(key string) (string, error) {
	val, err := util.RedisClient.RPop(ctx, key).Result()
	if err != nil {
		if err == redis.Nil {
			return "", nil
		}
		return "", err
	}
	return val, nil
}

// LRange 获取列表指定范围的元素（0表示第一个，-1表示最后一个）
func LRange(key string, start, stop int64) ([]string, error) {
	return util.RedisClient.LRange(ctx, key, start, stop).Result()
}
